/***********************************************************************
	filename: 	DaterEventFactoryManager.cpp
	created:	14/04/2012
	author:		4Ys
	
	purpose:	Implements the EventFactoryManager
*************************************************************************/

#include "DaterEventFacotryManager.h"

#include <algorithm>

namespace Dater
{
	//----------------------------------------------------------------------------//
	// singleton instance pointer
	template<> EventFactoryManager* Singleton<EventFactoryManager>::ms_Singleton = 0;

	// list of owned WindowFactory object pointers
	EventFactoryManager::OwnedEventFactoryList EventFactoryManager::d_ownedFactories;

	//----------------------------------------------------------------------------//
	EventFactoryManager::EventFactoryManager(void)
	{
		// complete addition of any pre-added WindowFactory objects
		EventFactoryManager::OwnedEventFactoryList::iterator i =
			d_ownedFactories.begin();

		if (d_ownedFactories.end() != i)
		{
			for (; d_ownedFactories.end() != i; ++i)
				addFactory(*i);
		}
	}

	//----------------------------------------------------------------------------//
	void EventFactoryManager::addFactory(EventFactory* factory)
	{
		// throw exception if passed factory is null.
		if (!factory)
		{
		}

		// throw exception if type name for factory is already in use
		if (d_factoryRegistry.find(factory->getTypeName()) != d_factoryRegistry.end())
		{
		}

		// add the factory to the registry
		d_factoryRegistry[factory->getTypeName()] = factory;
		/*
		char addr_buff[32];
		sprintf(addr_buff, "(%p)", static_cast<void*>(factory));
		Logger::getSingleton().logEvent("WindowFactory for '" +
		   factory->getTypeName() +"' windows added. " + addr_buff);*/
	}

	//----------------------------------------------------------------------------//
	void EventFactoryManager::removeFactory(const std::string& name)
	{
		EventFactoryRegistry::iterator i = d_factoryRegistry.find(name);

		// exit if no factory exists for this type
		if (i == d_factoryRegistry.end())
			return;

		// see if we own this factory
		OwnedEventFactoryList::iterator j = std::find(d_ownedFactories.begin(),
													   d_ownedFactories.end(),
													   (*i).second);

		/*char addr_buff[32];
		sprintf(addr_buff, "(%p)", static_cast<void*>((*i).second));*/

		d_factoryRegistry.erase(name);

		/*Logger::getSingleton().logEvent("WindowFactory for '" + name +
										"' windows removed. " + addr_buff);*/

		// delete factory object if we created it
		if (j != d_ownedFactories.end())
		{
			/*Logger::getSingleton().logEvent("Deleted WindowFactory for '" +
											(*j)->getTypeName() +
											"' windows.");*/

			delete (*j);
			d_ownedFactories.erase(j);
		}
	}

	//----------------------------------------------------------------------------//
	void EventFactoryManager::removeFactory(EventFactory* factory)
	{
		if (factory)
		{
			removeFactory(factory->getTypeName());
		}

	}

	//----------------------------------------------------------------------------//
	void EventFactoryManager::removeAllFactories(void)
	{
		while (!d_factoryRegistry.empty())
			removeFactory((*d_factoryRegistry.begin()).second);
	}

	//----------------------------------------------------------------------------//
	EventFactory* EventFactoryManager::getFactory(const std::string& type) const
	{
		// try for a 'real' type
		EventFactoryRegistry::const_iterator pos = d_factoryRegistry.find(type);

		// found an actual factory for this type
		if (pos != d_factoryRegistry.end())
		{
			return pos->second;
		}
		// no concrete type, try for a falagard mapped type
		else
		{
			// type not found anywhere, give up with an exception.
			throw(1);
		}
	}

	//----------------------------------------------------------------------------//
}